
function undateView () {
  console.log('更新视图')
}

// const oldArrProto = Array.prototype
// // 创建新对象，原型指向oldArrayProperty,再扩展新的方法不会影响原型
// const newArrProto = Object.create(oldArrProto)
// const methodArr = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
// methodArr.forEach(methodName => {
//   newArrProto[methodName] = function () {
//     undateView()
//     oldArrProto[methodName].call(this, ...arguments)
//   }
// })

const oldArrProto = Array.prototype
const newArrProto = Object.create(oldArrProto)
const methodArr = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
methodArr.forEach(methodName => {
  newArrProto[methodName] = function () {
    undateView()
    oldArrProto[methodName].call(this, ...arguments)
  }
})

function def (target, key, value) {
  observer(value)

  Object.defineProperty(target, key, {
    get () {
      return value
    },
    set (newValue) {
      if (value !== newValue) {
        observer(newValue)
        value = newValue
        undateView()
      }
    }
  })
}

function observer (target) {
  if (typeof target !== 'object' || target === null) {
    return target
  }

  if (Array.isArray(target)) {
    target.__proto__ = newArrProto
  }
  for (let key in target) {
    def(target, key, target[key])
  }
}

// 准备数据
const data = {
  name: 'zs',
  age: 20,
  info: {
    address: 'beijing' // 需要深度监听
  },
  nums: [10, 20, 30]
}

// 监听数据
observer(data)

// 测试
// console.log('age', data.age)
data.name = 'ls'
// data.age = 21
// console.log('age', data.age)
// // data.x = '100'
// // delete data.name
data.info.address = 'shanghai'
data.nums.push(4)